package com.general.framework.thread;

/**
 * CountDownLatch则是一个一次性使用的同步工具，通过一个计数器来触发等待操作
 * 初始时，计数器的值等于需要等待的线程数量。
 * 每当一个线程完成任务后，它会调用countDown()方法使计数器减1。
 * 当计数器达到0时，所有等待的线程会被释放继续执行
 *
 *  * CyclicBarrier适合用于一组线程需要相互等待达到共同状态然后同时开始或继续执行后续操作的场景。
 *  * 而CountDownLatch适用于一个或多个线程需要等待其他线程完成某个操作后才能继续执行的场景
 *  CountDownLatch 会阻塞主线程，直到计数器归零
 *  CyclicBarrier 不会阻塞主线程，只是阻塞了子线程
 *  CountDownLatch 是一次性使用的，而CyclicBarrier 可以重复使用
 */
public class CountDownLatchDemo {
    private int count;

    public CountDownLatchDemo(int count) {
        this.count = count;
    }

    public void await() throws InterruptedException {
        synchronized (this) {
            while (count > 0) {
                this.wait();
            }
        }
    }

    public void countDown() {
        synchronized (this) {
            if (count > 0) {
                count--;
                if (count == 0) {
                    this.notifyAll();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatchDemo countDownLatchDemo = new CountDownLatchDemo(5);
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 线程执行完毕");
                // 计数器减一
                countDownLatchDemo.countDown();
            }, String.valueOf(i)).start();
        }
        // 计数器归零之后，主线程继续执行
        countDownLatchDemo.await();
        System.out.println("所有线程均以执行完毕");
    }
}
